package ru.gerunn.silent.server;

import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import javax.net.ssl.SSLSocket;

import org.apache.log4j.Logger;

import ru.gerunn.silent.exception.SilentReadMessageException;
import ru.gerunn.silent.exception.SilentReaderException;
import ru.gerunn.silent.exception.SilentSessionException;
import ru.gerunn.silent.exception.SilentWriteMessageException;
import ru.gerunn.silent.exception.SilentWriterException;
import ru.gerunn.silent.io.Reader;
import ru.gerunn.silent.io.SocketReader;
import ru.gerunn.silent.io.SocketWriter;
import ru.gerunn.silent.io.Writer;
import ru.gerunn.silent.message.Message;
import ru.gerunn.silent.user.User;

public class Session {

	public static Logger log = Logger.getLogger(Session.class);

	private final SSLSocket socket;
	private final Reader reader;
	private final Writer writer;
	private String id;
	private boolean authentificated;
	private User user;

	public Session(SSLSocket socket) throws SilentReaderException, SilentWriterException {
		this.socket = socket;
		this.reader = new SocketReader(socket);
		this.writer = new SocketWriter(socket);
		this.setAuthentificated(false);
		log.info("session created");
	}

	public void start() throws SilentSessionException, SilentReadMessageException {
		log.info("session started authentificate");
		user = authentificate();
		if (user != null) {
			setAuthentificated(true);
			log.info("Username '" + user.getName() + "' authorized");

			Message message = null;
			while ((message = getReader().read()) != null) {
				System.out.println(user.getName() + ":\t" + message.toString());
			}

			this.close();
		} else {
			log.info("Username fails authorization");
			this.close();
		}
	}

	private User authentificate() {
		ExecutorService pool = Executors.newFixedThreadPool(1);
		Future<User> future = pool.submit(new Authentificator(this));
		User user = null;
		try {
			user = future.get();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (ExecutionException e) {
			e.printStackTrace();
		}

		return user;
	}

	public void write(Message message) throws SilentWriteMessageException {
		getWriter().write(message);
	}

	public void close() throws SilentSessionException {
		try {
			socket.close();
		} catch (IOException e) {
			throw new SilentSessionException("", e);
		}
	}

	public SSLSocket getSocket() {
		return socket;
	}

	public Reader getReader() {
		return reader;
	}

	public Writer getWriter() {
		return writer;
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		this.id = id;
	}

	public boolean isAuthentificated() {
		return authentificated;
	}

	public void setAuthentificated(boolean authentificated) {
		this.authentificated = authentificated;
	}

}
